import datetime
import time
from typing import Union, List, Any
from fastapi import FastAPI, Path, Query, HTTPException
import uvicorn
# from lxml.parser import result
from pydantic import BaseModel, EmailStr
from fastapi import Cookie
from fastapi import Header
from fastapi import Form, File, UploadFile
from fastapi.responses import HTMLResponse
from fastapi import Request, status
from fastapi.responses import JSONResponse
from fastapi.exceptions import RequestValidationError
from fastapi.responses import PlainTextResponse
from starlette.exceptions import HTTPException as StarletteHTTPException
from fastapi.encoders import jsonable_encoder
from fastapi import Depends
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from starlette.middleware.cors import CORSMiddleware

from demo2 import response

app = FastAPI()

# 通行列表
origins = [
    "http://localhost.tiangolo.com",
    "https://localhost.tiangolo.com",
    "https://localhost",
    "https://localhost:8080",
]

# 添加放行的中间件
app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=["*"],  # 允许跨域的请求方法
    allow_headers=["*"],
)


@app.get("/")
async def main():
    return {"message": "Hello World"}


@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
    start_time = time.time()
    response = await call_next(request)
    process_time = time.time() - start_time
    response.headers["X-Process-Time"] = str(process_time)
    return response


# # 模拟用户数据
# fake_users_db = {
#     "johndoe": {
#         "username": "johndoe",
#         "full_name": "John Doe",
#         "email": "",
#         "hashed_password": "fakehashedsecret",
#         "disabled": False,
#     },
#     "alice": {
#         "username": "alice",
#         "full_name": "Alice Wonderson",
#         "email": "",
#         "hashed_password": "fakehashedsecret2",
#         "disabled": True,
#    },
# }
#
# app = FastAPI()
#
# # 处理password参数
# def fake_hash_password(password: str):
#     return "fakehashed" + password
#
#
# # 安全性验证
# oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
#
# # 定义请求参数模型
# class User(BaseModel):
#     username: str
#     email: Union[str,None] = None
#     full_name: Union[str, None] = None
#     disabled: Union[bool, None] = None
#
# # # 定义token的组成
# # def fake_decode_token(token: str):
# #     return User(username=token + "fakedecoded", email="", full_name="Antony")
#
# class UserInDB(User):
#     hashed_password: str
#
# # 判断用户是否在数据库
# def get_user(db,username: str):
#     if username in db:
#         user_dict = db[username]
#         return UserInDB(**user_dict)
#
# def fake_decode_token(token):
#     user = get_user(fake_users_db,token)
#     return user
#
# async def get_current_user(token: str = Depends(oauth2_scheme)):
#     user = fake_decode_token(token)
#     if not user:
#         raise HTTPException(
#             status_code=status.HTTP_401_UNAUTHORIZED,
#             detail="Invalid authentication credentials",
#             headers={"WWW-Authenticate": "Bearer"},
#         )
#     return user
# async def get_current_active_user(current_user: User = Depends(get_current_user)):
#     if current_user.disabled:
#         raise HTTPException(status_code=400, detail="Inactive user")
#     return current_user
# @app.post("/token")
# async def login(form_data: OAuth2PasswordRequestForm = Depends()):
#     user_dict = fake_users_db.get(form_data.username)
#     if not user_dict:
#         raise HTTPException(status_code=400, detail="Incorrect username or password")
#     user = UserInDB(**user_dict)
#     hashed_password = fake_hash_password(form_data.password)
#     if not hashed_password == user.hashed_password:
#         raise HTTPException(status_code=400, detail="Incorrect username or password")
#     return {"access_token": user.username, "token_type": "bearer"}
# @app.get("/users/me")
# async def read_users_me(current_user: User = Depends(get_current_active_user)):
#     return current_user

# # 验证token
# async def get_current_user(token: str = Depends(oauth2_scheme)):
#     user = fake_decode_token(token)
#     return user
#
# @app.get("/users/me")
# async def read_users_me(current_user: User = Depends(get_current_user)):
#     return current_user
#
# # 依赖注入安全验证,只要验证通过，依赖项才会被调用
# @app.get("/items//")
# async def read_items(token: str = Depends(oauth2_scheme)):
#     return {"token": token}


# # 定义全局依赖项
# async def verify_token(x_token: str = Header()):
#     if x_token != "fake-super-secret-token":
#         raise HTTPException(status_code=400, detail="X-Token header invalid")
#
# async def verify_key(x_key: str = Header()):
#     if x_key != "fake-super-secret-key":
#         raise HTTPException(status_code=400, detail="X-Key header invalid")
#
# # 创建app 对象
# app = FastAPI(dependencies=[Depends(verify_token), Depends(verify_key)])
#
# # 定义路由
# @app.get("/items/")
# async def read_items_v1():
#     return [{"item":"Portal Gun"},{"item":"Plumbus"}]
#
# # 定义路由
# @app.get("/users/")
# async def read_users():
#     return [{"username":"john"},{"username":"alice"}]
#
# class Item(BaseModel):
#     name: str
#     description: Union[str, None] = None
#     price: float
#     tax: Union[float, None] = None
#     tags: List[str] = []
#
#
# class User(BaseModel):
#     username: str
#     full_name: Union[str, None] = None
#
#
# # 带cookie调用
# @app.get("/items/")
# async def read_items_1(ads_id: Union[str, None] = Cookie(default=None)):
#     return {"ads_id": ads_id}
#
#
# # 带header调用
# @app.get("/items_1/")
# async def read_items_2(user_agent: Union[str, None] = Header(default=None)):
#     return {"User-Agent": user_agent}
#
#
# # @app.get("/")
# # async def root():
# #     return {"message": "Hello World"}
# #
# #
# @app.get("/items/{item_id}")
# async def read_items(
#         item_id: int = Path(title="The ID of the item to get"),
#         q: Union[str, None] = Query(default=None, alias="item-query"),
# ):
#     results = {"item_id": item_id}
#     if q:
#         results.update({"q": q})
#     return results
#
#
# #
# # @app.post("/items_v1")
# # async def create_item(item: Item):
# #     item = Item(name="Foo", description="The pretiest foo you have ever had!", price=42.0, tax=3.2)
# #     return item
#
# @app.post("/items")
# async def create_item(item: Item):
#     return item.model_dump()
#
#
# @app.put("/items/{item_id}")
# async def update_item(
#         *,
#         item_id: int = Path(title="The ID of the item to get", ge=0, le=1000),
#         q: Union[str, None] = None,
#         item: Union[Item, None] = None
# ):
#     results = {"item_id": item_id}
#     if q:
#         results.update({"q": q})
#     if item:
#         results.update({"item": item.model_dump()})
#     return results
#
#
# class Items(BaseModel):
#     name: str
#     description: Union[str, None] = None
#     price: float
#     tax: Union[float, None] = None
#     tags: list[str] = []
#
#
# # 响应
# @app.post("/items/", response_model=Items)
# async def create_item_v1(item: Items) -> Any:
#     return item
#
#
# @app.get("/items/", response_model=List[Items])
# async def read_items_v2() -> Any:
#     return [
#         {"name": "Foo", "price": 42.0},
#         {"name": "Bar", "price": 50.0}
#     ]
#
#
# # 创建用户输入数据
# class UserIn(BaseModel):
#     username: str
#     password: str
#     email: EmailStr
#     full_name: Union[str, None] = None
#
#
# # 创建用户输出数据
# class UserOut(BaseModel):
#     username: str
#     email: EmailStr
#     full_name: Union[str, None] = None
#
#
# # 定义响应数据
# @app.post("/user/", response_model=UserOut)
# async def create_user(user: UserIn) -> Any:
#     return user
#
#
# # 响应模型可以具有默认值
# class ItemResponse(BaseModel):
#     name: str
#     description: Union[str, None] = None
#     price: float
#     tax: float = 10.5
#     tags: list[str] = []
#
#
# Items = {
#     "foo": {"name": "Foo", "price": 50.2},
#     "bar": {"name": "Bar", "description": "The bartenders", "price": 62, "tax": 20.2},
#     "baz": {"name": "Baz", "description": None, "price": 50.2, "tax": 10.5, "tags": []}
# }
#
#
# # 设置响应模型
# @app.get("/items/{item_id}", response_model=Item, response_model_exclude_unset=True)
# async def read_item(item_id: str) -> Any:
#     return Items[item_id]
#
#
# # 密码模型
# # userIn 接收用户输入数据
# class UserIn(BaseModel):
#     username: str  # 用户名
#     password: str  # 密码
#     email: EmailStr  # 邮箱
#     full_name: Union[str, None] = None  # 全名
#
#
# # UserOut 输出数据
# class UserOut(BaseModel):
#     username: str  # 用户名
#     email: EmailStr  # 邮箱
#     full_name: Union[str, None] = None  # 全名 可选
#
#
# # UserInDB 用于存储在数据库中的用户数据
# class UserInDB(BaseModel):
#     username: str  # 用户名
#     hashed_password: str  # 加密后的密码
#     email: EmailStr  # 邮箱
#     full_name: Union[str, None] = None  # 全名 可选
#
#
# # 创建伪哈希函数
# def fake_password_hasher(raw_password: str):
#     """
#     伪密码哈希函数 用于模拟密码哈希过程
#     :param raw_password: 原始密码
#     :return: str 返回加密后的密码
#     """
#     return "supersecret" + raw_password
#
#
# # 创建伪用户保存函数
# def fake_save_user(user_in: UserIn):
#     """
#     伪用户保存函数 用于模拟用户保存过程
#     :param user_in: 用户输入数据
#     :return: None
#     """
#     hashed_password = fake_password_hasher(user_in.password)
#     user_in_db = UserInDB(**user_in.model_dump(), hashed_password=hashed_password)
#     print("User saved! ..not really")
#     return user_in_db
#
#
# # 定义一个 post 路由,用于创建新用户
# @app.post("/user/", response_model=UserOut)
# async def create_user(user_in: UserIn):
#     """
#     创建新用户
#
#     :param user_in: 用户输入的数据
#     :return: user_out: 返回给客户端的用户数据
#     """
#     user_saved = fake_save_user(user_in)
#     return user_saved
#
#
# @app.post("/login/")
# async def login(username: str = Form(), password: str = Form()):
#     """
#     用户登录
#
#     :param username: 用户名
#     :param password: 密码
#     :return:
#     """
#     return {"username": username}
#
#
# @app.post("/files/")
# async def create_file(file: bytes = File()):
#     """
#     上传文件
#
#     :param file: 文件对象
#     :return:
#     """
#     return {"file_size": len(file)}
#
#
# @app.post("/uploadFile1/")
# async def create_upload_file(file: UploadFile):
#     """
#     上传文件
#
#     :param file:
#     :return:
#     """
#     return {"filename": file.filename}
#
#
# # 带有可选上传文件
# @app.post("/files1/")
# async def create_file_v1(file: Union[bytes, None] = File(default=None)):
#     if not file:
#         return {"message": "No file sent"}
#     else:
#         return {"file_size": len(file)}
#
#
# # 带有可选上传文件-uploadfile
# @app.post("/uploadFile2/")
# async def create_upload_file_v1(file: Union[UploadFile, None] = None):
#     if not file:
#         return {"message": "No file sent"}
#     else:
#         return {"filename": file.filename}
#
#
# # 带有额外元数据的 uploadFile
# @app.post("/files2/")
# async def create_file_v2(file: bytes = File(description="A file read as bytes")):
#     return {"file_size": len(file)}
#
#
# @app.post("/uploadFile3/")
# async def create_upload_file_v2(
#         file: UploadFile = File(description="A file read as UploadFile"),
# ):
#     return {"filename": file.filename}
#
#
# # 多文件上传
# @app.post("/files3/")
# async def create_file_v3(files: List[bytes] = File()):
#     """
#     上传多个文件
#
#     :param files: 文件对象列表
#     :return:
#     """
#     return {"file_sizes": [len(file) for file in files]}
#
#
# @app.get("/")
# async def main():
#     content = """
#     <body>
#     <form action="/files/" enctype="multipart/form-data" method="post">
#     <input name="files" type="file" multiple>
#     <input type="submit">
#     </form>
#     <form action="/uploadfiles/" enctype="multipart/form-data" method="post">
#     <input name="files" type="file" multiple>
#     <input type="submit">
#     </form>
#     </body>
#     """
#     return HTMLResponse(content=content)
#
#
# @app.post("/files4/")
# async def create_file_v4(files: bytes = File(), fileb: UploadFile = File(), token: str = Form()):
#     """
#     上传文件
#
#     :param files: 文件对象
#     :return:
#     """
#     return {
#         "file_size": len(files),
#         "token": token,
#         "fileb_content_type": fileb.content_type
#     }
#
#
# items = {"foo": "The Foo Wrestlers"}
#
#
# # 返回http错误响应
# @app.get("/items/{item_id}")
# async def read_item_v1(item_id: str):
#     """
#     返回http错误响应
#
#     :param item_id:
#     :return:
#     """
#     if item_id not in items:
#         raise HTTPException(status_code=404, detail="Item not found")
#     return {"item_id": items[item_id]}
#
#
# # 添加自定义响应头
# @app.get("/items-header/{item_id}")
# async def read_item_header(item_id: str):
#     """
#     添加自定义响应头
#
#     :param item_id:
#     :return:
#     """
#     if item_id not in items:
#         raise HTTPException(
#             status_code=404,
#             detail="Item not found",
#             headers={"X-Error": "There goes my error"}
#         )
#     return {"item_id": items[item_id]}
#
#
# # 自定义异常控制器
# class UnicornException(Exception):
#     def __init__(self, name: str):
#         self.name = name
#
#
# @app.exception_handler(UnicornException)
# async def unicorn_exception_handler(request: Request, exc: UnicornException):
#     """
#     自定义异常控制器
#
#     :param request:
#     :param exc:
#     :return:
#     """
#     return JSONResponse(
#         status_code=418,
#         content={"message": f"Oops! {exc.name} did something. There goes a rainbow..."},
#     )
#
#
# @app.get("/unicorns/{name}")
# async def read_unicorn(name: str):
#     """
#     自定义异常控制器
#
#     :param name:
#     :return:
#     """
#     if name == "yolo":
#         raise UnicornException(name=name)
#     return {"unicorn_name": name}
#
#
# # 定义StarletteHTTPException的异常处理器
# @app.exception_handler(StarletteHTTPException)
# async def http_exception_handler(request, exc):
#     # 返回一个纯文本响应，内容为异常详情，状态码为异常的状态码
#     return PlainTextResponse(str(exc.detail), status_code=exc.status_code)
#
#
# # 定义RequestValidationError的异常处理器
# @app.exception_handler(RequestValidationError)
# async def validation_exception_handler(request, exc):
#     """
#     覆盖异常处理器
#
#     :param request: 请求对象
#     :param exc: 异常对象
#     :return: 响应对象
#     """
#     # 返回一个纯文本响应，内容为异常详情，状态码为400
#     return PlainTextResponse(str(exc), status_code=400)
#
#
# # 定义路由处理函数
# @app.get("/items/{item_id}")
# async def read_item_v2(item_id: int):
#     # 如果item_id等于3，则抛出HTTPException
#     if item_id == 3:
#         raise HTTPException(status_code=418, detail="Nope! I don't like 3.")
#     # 否则返回包含item_id的字典
#     return {"item_id": item_id}
#
#
# # 使用RequestValidationError 包含其接收到的无效数据请求的 body
# @app.exception_handler(RequestValidationError)
# async def validation_exception_handler_v2(request: Request, exc: RequestValidationError):
#     """
#
#     :param request:
#     :param exc:
#     :return:
#     """
#     return JSONResponse(
#         status_code= status.Http_422_UNPROCESSABLE_ENTITY,
#         content=jsonable_encoder({"detail": exc.errors(), "body": exc.body}),
#     )
#
#
# class Item1(BaseModel):
#     title: str
#     size: int
#
# @app.post("/items/")
# async def care_item1(item: Item1):
#     return item
#
#
# fake_db = {}
#
# class Item2(BaseModel):
#     title: str
#     timestamp : datetime
#     description: Union[str] = None
#
#
# @app.put("/items/{id}")
# def undate_item(id: str, item: Item2):
#     json_compatible_item_data = jsonable_encoder(item)
#     fake_db[id] = json_compatible_item_data
#
#
# class Item3(BaseModel):
#     name: Union[str,None] = None
#     description: Union[str,None] = None
#     price: Union[float,None] = None
#     tax: float = 10.5
#     tags: List[str] = []
#
# Items4 = {
#     "foo": {"name": "Foo", "price": 50.2},
#     "bar": {"name": "Bar", "description": "The bartenders", "price": 62, "tax": 20.2},
#     "baz": {"name": "Baz", "description": None, "price": 50.2, "tax": 10.5, "tags": []},
# }
#
# # 获取传递的参数
# @app.get("/items/{item_id}",response_model=Item3)
# async def read_item(item_id: str):
#     return Items4[item_id]
#
# # 更新请求体
# @app.put("/items/{item_id}", response_model=Item3)
# async def update_item(item_id: str, item: Item3):
#     """
#     更新请求体
#
#     :param item_id:
#     :param item:
#     :return:
#     """
#     update_item_encoded = jsonable_encoder(item)
#     Items4[item_id].update(update_item_encoded)
#     return update_item_encoded
#
#
# # 依赖注入
# async def common_parameters(q:Union[str,None] = None,skip:int = 0,limit:int = 100):
#     return {"q":q,"skip":skip,"limit":limit}
#
# @app.get("/items/")
# async def read_items_v2(commons:dict = Depends(common_parameters)):
#     return commons
#
# @app.get("/users/")
# async def read_users(commons:dict = Depends(common_parameters)):
#     """
#     依赖注入
#
#     :param commons:
#     :return:
#     """
#     return commons
#
#
#
#
# fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]
#
# class CommonQueryParams:
#     def __init__(self, q: Union[str, None] = None, skip: int = 0, limit: int = 100):
#         self.q = q
#         self.skip = skip
#         self.limit = limit
#
# @app.get("/items/")
# async def read_items_v3(commons: CommonQueryParams = Depends(CommonQueryParams)):
#     """
#     依赖注入
#
#     :param commons:
#     :return:
#     """
#     response = {}
#     if commons.q:
#         response.update({"q": commons.q})
#     items1 = fake_items_db[commons.skip : commons.skip + commons.limit]
#     response.update({"items": items1})
#     return response
#
# # 创建第一层依赖
# def query_extractor(q: Union[str, None] = None):
#     return q
#
# def query_or_cookie_extractor(
#         q: str = Depends(query_extractor),
#         last_query: Union[str, None] = Cookie(default=None),
# ):
#     if not q:
#         return last_query
#     return q
#
# @app.get("/items/")
# async def  read_query(query_or_default: str = Depends(query_or_cookie_extractor)):
#     """
#     依赖注入
#
#     :param query_or_default:
#     :return:
#     """
#     return {"q_or_cookie": query_or_default}


if __name__ == '__main__':
    uvicorn.run("main:app", host="127.0.0.1", port=8001, log_level="debug")
